package chess

import (
	"fmt"
	"sync"

	"gddgame.cc/galaxy/common/feature/orbit"
	"gddgame.cc/galaxy/common/feature/orbit/chess_protocol"
	"gddgame.cc/galaxy/utils"
)

type NodeManager struct {
	Nodes     NodeSlice
	NodeIndex sync.Map

	block *orbit.BlockLocation
}

func NewNodeManager(block *orbit.BlockLocation) NodeManager {
	//size := block.Size()
	data := NodeManager{
		Nodes:     []*chess_protocol.Data{},
		NodeIndex: sync.Map{},

		block: block,
	}

	return data
}

func (dm *NodeManager) Add(data *chess_protocol.Data) *chess_protocol.Data {
	dm.Set(data)
	return data
}

func (dm *NodeManager) Message(message *chess_protocol.SendMessage) *chess_protocol.Data {
	fmt.Println("node message", message.DataType, message.Id)
	node := dm.getNode(utils.ToBytes(message.Id))
	node.SendMessage(message.Message)
	return node
}

func (dm *NodeManager) getNode(position []byte) *chess_protocol.Data {
	index := orbit.LocationCM.IndexInBlock(dm.block, position)
	//defer func() {
	//	if err := recover(); err != nil {
	//		// 如果node消息是其他类型消息
	//		// 可能是因为schedule消息堆积，全部直接执行后导致发送movedata的数据并行处理
	//		// 没有能实现到movedata的切换逻辑，2～3个节点后就发生datamanage数据为空，将消息转发到node
	//		fmt.Println("node error", len(dm.NodeIndex), position, index)
	//	}
	//}()
	var nn *chess_protocol.Data
	n, ok := dm.NodeIndex.Load(index)
	if !ok {
		nn = &chess_protocol.Data{
			Position: position,
			Extend:   [][]chess_protocol.ExtendItem{},
			ListId:   [][]string{},
			ListNo:   [][]int{},
			ListNode: [][][]byte{},
		}

		dm.NodeIndex.Store(index, len(dm.Nodes))
		dm.Nodes = append(dm.Nodes, nn)
	} else {
		index = utils.ToInt(n)
		nn = dm.Nodes[index]
	}
	return nn
}

//
//func (dm *NodeManager) Update(data *chess_protocol.UpdateNode) *chess_protocol.Data {
//	//fmt.Println("node update", data.Data)
//	node := dm.getNode(data.Position)
//	node.Range = data.Range
//	node.UpdateProp(data.Data.Props)
//	node.UpdateExtend(data.Data.Extend)
//	node.ResetExtend(data.Data.Reset)
//	node.UpdateBeDependent(data.Data.BeDependents)
//	node.UpdateOwnNodes(data.Data.OwnNodes)
//	node.SendMessage(data.Data.Message)
//	return node
//}

func (dm *NodeManager) Set(data *chess_protocol.Data) {
	index := orbit.LocationCM.IndexInBlock(dm.block, data.Position)
	n, ok := dm.NodeIndex.Load(index)
	//fmt.Println("create node", len(dm.NodeIndex), len(dm.Nodes), index, n)
	if !ok {
		dm.NodeIndex.Store(index, len(dm.Nodes))
		dm.Nodes = append(dm.Nodes, data)
	} else {
		index = utils.ToInt(n)
		dm.Nodes[index] = data
	}
}
